import { ref, computed, onMounted, onUnmounted, nextTick, readonly } from 'vue'

export interface VirtualKeyboardState {
  isVisible: boolean
  height: number
  previousHeight: number
  isTransitioning: boolean
}

/**
 * Virtual keyboard composable for handling mobile keyboard interactions
 */
export function useVirtualKeyboard() {
  // State
  const windowHeight = ref(window.innerHeight)
  const visualViewportHeight = ref(window.visualViewport?.height || window.innerHeight)
  const isKeyboardVisible = ref(false)
  const keyboardHeight = ref(0)
  const previousKeyboardHeight = ref(0)
  const isTransitioning = ref(false)
  const transitionTimeout = ref<NodeJS.Timeout | null>(null)

  // Computed
  const keyboardState = computed((): VirtualKeyboardState => ({
    isVisible: isKeyboardVisible.value,
    height: keyboardHeight.value,
    previousHeight: previousKeyboardHeight.value,
    isTransitioning: isTransitioning.value
  }))

  // Threshold for detecting keyboard (in pixels)
  const KEYBOARD_THRESHOLD = 150

  // Update keyboard state
  const updateKeyboardState = () => {
    const currentViewportHeight = window.visualViewport?.height || window.innerHeight
    const heightDifference = windowHeight.value - currentViewportHeight
    
    const wasVisible = isKeyboardVisible.value
    const newIsVisible = heightDifference > KEYBOARD_THRESHOLD
    
    if (newIsVisible !== wasVisible) {
      isTransitioning.value = true
      
      // Clear existing timeout
      if (transitionTimeout.value) {
        clearTimeout(transitionTimeout.value)
      }
      
      // Set transition end timeout
      transitionTimeout.value = setTimeout(() => {
        isTransitioning.value = false
      }, 300) // Match typical keyboard animation duration
    }
    
    previousKeyboardHeight.value = keyboardHeight.value
    isKeyboardVisible.value = newIsVisible
    keyboardHeight.value = newIsVisible ? heightDifference : 0
    visualViewportHeight.value = currentViewportHeight
  }

  // Handle window resize (fallback for older browsers)
  const handleWindowResize = () => {
    const newHeight = window.innerHeight
    const heightDifference = windowHeight.value - newHeight
    
    // Only update if significant change (likely keyboard)
    if (Math.abs(heightDifference) > KEYBOARD_THRESHOLD) {
      updateKeyboardState()
    }
  }

  // Handle visual viewport changes (modern browsers)
  const handleVisualViewportChange = () => {
    updateKeyboardState()
  }

  // Adjust element for keyboard
  const adjustForKeyboard = (element: HTMLElement, options: {
    paddingBottom?: boolean
    translateY?: boolean
    maintainViewport?: boolean
  } = {}) => {
    const { paddingBottom = true, translateY = false, maintainViewport = false } = options
    
    if (isKeyboardVisible.value) {
      if (paddingBottom) {
        element.style.paddingBottom = `${keyboardHeight.value}px`
      }
      
      if (translateY) {
        element.style.transform = `translateY(-${keyboardHeight.value / 2}px)`
      }
      
      if (maintainViewport) {
        element.style.height = `${visualViewportHeight.value}px`
      }
    } else {
      if (paddingBottom) {
        element.style.paddingBottom = ''
      }
      
      if (translateY) {
        element.style.transform = ''
      }
      
      if (maintainViewport) {
        element.style.height = ''
      }
    }
  }

  // Scroll element into view when keyboard appears
  const scrollIntoView = (element: HTMLElement, options: {
    behavior?: ScrollBehavior
    block?: ScrollLogicalPosition
    inline?: ScrollLogicalPosition
    offset?: number
  } = {}) => {
    if (!isKeyboardVisible.value) return
    
    const { behavior = 'smooth', block = 'center', inline = 'nearest', offset = 0 } = options
    
    nextTick(() => {
      const rect = element.getBoundingClientRect()
      const viewportHeight = visualViewportHeight.value
      const elementBottom = rect.bottom + offset
      
      if (elementBottom > viewportHeight) {
        element.scrollIntoView({
          behavior,
          block,
          inline
        })
      }
    })
  }

  // Focus management for inputs
  const handleInputFocus = (inputElement: HTMLElement, options: {
    scrollIntoView?: boolean
    adjustContainer?: HTMLElement
    adjustOptions?: Parameters<typeof adjustForKeyboard>[1]
  } = {}) => {
    const { scrollIntoView: shouldScroll = true, adjustContainer, adjustOptions } = options
    
    // Wait for keyboard to appear
    setTimeout(() => {
      if (shouldScroll) {
        scrollIntoView(inputElement)
      }
      
      if (adjustContainer) {
        adjustForKeyboard(adjustContainer, adjustOptions)
      }
    }, 100)
  }

  // Prevent zoom on input focus (iOS)
  const preventZoomOnFocus = (inputElement: HTMLInputElement | HTMLTextAreaElement) => {
    const originalFontSize = inputElement.style.fontSize
    const originalTransform = inputElement.style.transform
    
    const handleFocus = () => {
      inputElement.style.fontSize = '16px' // Prevent zoom on iOS
    }
    
    const handleBlur = () => {
      inputElement.style.fontSize = originalFontSize
      inputElement.style.transform = originalTransform
    }
    
    inputElement.addEventListener('focus', handleFocus)
    inputElement.addEventListener('blur', handleBlur)
    
    return () => {
      inputElement.removeEventListener('focus', handleFocus)
      inputElement.removeEventListener('blur', handleBlur)
    }
  }

  // Get safe area for content positioning
  const getSafeArea = () => {
    const safeAreaTop = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sat') || '0')
    const safeAreaBottom = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sab') || '0')
    
    return {
      top: safeAreaTop,
      bottom: Math.max(safeAreaBottom, keyboardHeight.value),
      left: 0,
      right: 0
    }
  }

  // Apply safe area styles
  const applySafeAreaStyles = (element: HTMLElement) => {
    const safeArea = getSafeArea()
    
    element.style.paddingTop = `max(${element.style.paddingTop || '0px'}, ${safeArea.top}px)`
    element.style.paddingBottom = `max(${element.style.paddingBottom || '0px'}, ${safeArea.bottom}px)`
  }

  // Lifecycle
  onMounted(() => {
    windowHeight.value = window.innerHeight
    
    // Use Visual Viewport API if available (modern browsers)
    if (window.visualViewport) {
      window.visualViewport.addEventListener('resize', handleVisualViewportChange)
    } else {
      // Fallback for older browsers
      window.addEventListener('resize', handleWindowResize)
    }
    
    // Initial state
    updateKeyboardState()
  })

  onUnmounted(() => {
    if (window.visualViewport) {
      window.visualViewport.removeEventListener('resize', handleVisualViewportChange)
    } else {
      window.removeEventListener('resize', handleWindowResize)
    }
    
    if (transitionTimeout.value) {
      clearTimeout(transitionTimeout.value)
    }
  })

  return {
    // State
    keyboardState,
    isKeyboardVisible: readonly(isKeyboardVisible),
    keyboardHeight: readonly(keyboardHeight),
    visualViewportHeight: readonly(visualViewportHeight),
    isTransitioning: readonly(isTransitioning),
    
    // Methods
    adjustForKeyboard,
    scrollIntoView,
    handleInputFocus,
    preventZoomOnFocus,
    getSafeArea,
    applySafeAreaStyles
  }
}

// Utility function to detect if device has virtual keyboard
export function hasVirtualKeyboard(): boolean {
  return /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
}

// Utility function to get keyboard-safe viewport height
export function getKeyboardSafeHeight(): number {
  return window.visualViewport?.height || window.innerHeight
}